依存関係フローグラフの例
次の例では、A-E の 5 つの計算が下記の 「単純な依存関係グラフ」 のように半順序でセットアップされています。フローグラフの各エッジで、エッジの最後のノードは先頭のノードが開始する前に実行を完了していなければなりません。
#include <cstdio>
#include "oneapi/tbb/flow_graph.h"
using namespace oneapi::tbb::flow;
struct body {
std::string my_name;
body(const char *name) : my_name(name) {}
void operator()(continue_msg) const {
printf("%s\n", my_name.c_str());
}
};
int main() {
graph g;
broadcast_node< continue_msg > start(g);
continue_node<continue_msg> a(g, body("A"));
continue_node<continue_msg> b(g, body("B"));
continue_node<continue_msg> c(g, body("C"));
continue_node<continue_msg> d(g, body("D"));
continue_node<continue_msg> e(g, body("E"));
make_edge(start, a);
make_edge(start, b);
make_edge(a, c);
make_edge(b, c);
make_edge(c, d);
make_edge(a, e);
for (int i = 0; i < 3; ++i) {
start.try_put(continue_msg());
g.wait_for_all();
}
return 0;
}
この例では、ノード A-E がそれぞれの名前を出力します。そのため、これらのノードはすべて struct body
を使用してボディー・オブジェクトを構築できます。
main
関数で、フローグラフは一回セットアップされ、3 回実行されます。この例のノードはすべて、continue_msg
オブジェクトを使用します。このタイプは、ノードが実行完了したことを通知するために使用されます。
main
関数の最初の行は、graph
オブジェクト g
をインスタンス化します。次の行で、start
という名称の broadcast_node
を作成しています。このノードに渡されるものはすべて、その後続 (サクセサー) にブロードキャストされます。start
ノードは、main
の最後にある for
ループで残りのフローグラフを実行するために使用されます。
この例では、名前が a - e の 5 つの continue_node
オブジェクトが作成されます。各ノードは、graph
g
への参照と、実行時に呼び出す関数オブジェクトにより構築されます。後続 (サクセサー) / 先行 (プリディセッサー) の関係は、ノードの宣言に続く make_edge
呼び出しでセットアップされます。
ノードとエッジが設定された後、for
ループのそれぞれの反復で try_put
によって、a
と b
の両方に continue_msg
がブロードキャストされます。a
と b
のどちらも単一の continue_msg
を持っています。これは、どちらも先行する start
しか持たないためです。
start
からメッセージを受け取ると、ボディー・オブジェクトを実行します。完了すると、それぞれがサクセサーにメッセージを転送します。計算を並列に実行可能な場合、グラフは複数のタスクを使用してノード間でメッセージを送る処理と、ノードのボディーを実行する処理を並列に実行します。
参照: